package com.zzl.bonds.ticket.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzl.bonds.ticket.constant.TicketBookRelationTypeEnum;
import com.zzl.bonds.ticket.constant.status.SendStatusEnum;
import com.zzl.bonds.ticket.dao.TicketBookRelationDao;
import com.zzl.bonds.ticket.dto.bookrelation.TicketBookRelationAddDto;
import com.zzl.bonds.ticket.dto.bookrelation.TicketBookRelationBatchAddDto;
import com.zzl.bonds.ticket.dto.bookrelation.TicketBookRelationUpdateDto;
import com.zzl.bonds.ticket.entity.TicketBookRelationEntity;
import com.zzl.bonds.ticket.entity.feign.AddressBookEntity;
import com.zzl.bonds.ticket.entity.feign.SMSEmailParams;
import com.zzl.bonds.ticket.exception.SysExceptionFactory;
import com.zzl.bonds.ticket.feign.BaseDataFeign;
import com.zzl.bonds.ticket.feign.MsgFeign;
import com.zzl.bonds.ticket.service.TicketBookRelationService;
import com.zzl.bonds.ticket.service.common.SendMsgService;
import com.zzl.bonds.ticket.untils.TicketUtils;
import com.zzl.general.common.exception.SysException;
import com.zzl.general.common.serurity.entity.User;
import com.zzl.general.common.utils.PageUtils;
import com.zzl.general.common.utils.Query;
import com.zzl.general.common.utils.Result;
import com.zzl.general.common.utils.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.zzl.bonds.ticket.constant.status.SendStatusEnum.SEND_STATUS_NO;
import static com.zzl.bonds.ticket.constant.type.TicketBookRelationMsgTypeEnum.*;
import static com.zzl.bonds.ticket.exception.SysExceptionEnum.TICKET_SEND_FAIL;

/**
 * 联系人票关系表
 *
 * @author gull
 * @date 2021-12-07 16:29:41
 */
@Slf4j
@Service("ticketBookRelationService")
public class TicketBookRelationServiceImpl extends ServiceImpl<TicketBookRelationDao, TicketBookRelationEntity> implements TicketBookRelationService {
    @Autowired
    private SendMsgService sendMsgService;

    @Autowired
    private BaseDataFeign baseDataFeign;

    @Autowired
    private MsgFeign msgFeign;

    /**
     * 分页查询
     *
     * @param params 查询参数
     * @return 分页数据
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<TicketBookRelationEntity> page = this.page(
                new Query<TicketBookRelationEntity>().getPage(params),
                new QueryWrapper<>()
        );

        return new PageUtils(page);
    }

    /**
     * 新增
     *
     * @param tickebookRelationAddDto 新增实体
     * @param user                    当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void saveTickebookRelation(TicketBookRelationAddDto tickebookRelationAddDto, User user) throws SysException {
        TicketBookRelationEntity tickebookRelationEntity = new TicketBookRelationEntity();
        BeanUtils.copyProperties(tickebookRelationAddDto, tickebookRelationEntity);
        tickebookRelationEntity.setCreatorId(user.getId());
        if (!this.save(tickebookRelationEntity)) {
            throw new SysException("A00001", "保存失败！");
        }
    }

    /**
     * 修改
     *
     * @param tickebookRelationUpdateDto 修改实体
     * @param user                       当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void updateTickebookRelationById(TicketBookRelationUpdateDto tickebookRelationUpdateDto, User user) throws SysException {
        TicketBookRelationEntity tickebookRelationEntity = new TicketBookRelationEntity();
        BeanUtils.copyProperties(tickebookRelationUpdateDto, tickebookRelationEntity);
        tickebookRelationEntity.setUpdaterId(user.getId());
        if (!this.updateById(tickebookRelationEntity)) {
            throw new SysException("A00002", "修改失败！");
        }
    }

    /**
     * 发送消息，保存发送消息的信息
     *
     * @param ticketBookRelation 发消息和开立申请、异常申请关系
     * @param user               登录用户
     */
    @Override
    public void saveTicketBookRelationBatch(TicketBookRelationBatchAddDto ticketBookRelation, User user) throws SysException {
        if (!CollectionUtils.isEmpty(ticketBookRelation.getAddressBookIdList())) {
            List<TicketBookRelationEntity> list = new ArrayList<>();
            ticketBookRelation.getAddressBookIdList().forEach(x -> {
                ticketBookRelation.getObjIdList().forEach(y -> {
                    TicketBookRelationEntity ticketBookRelationEntity = new TicketBookRelationEntity();
                    ticketBookRelationEntity.setBusinessId(y);
                    ticketBookRelationEntity.setBusinessType(ticketBookRelation.getType());
                    ticketBookRelationEntity.setMessageType(ticketBookRelation.getMessageType());
                    ticketBookRelationEntity.setAddressBookId(x);
                    ticketBookRelationEntity.setCreatorId(user.getId());
                    ticketBookRelationEntity.setUpdaterId(user.getId());
                    ticketBookRelationEntity.setEnterpriseId(user.getEnterpriseId());
                    ticketBookRelationEntity.setSendStatus(SEND_STATUS_NO.getCode());
                    list.add(ticketBookRelationEntity);
                });
            });
            //批量保存
            if (!this.saveBatch(list)) {
                throw SysExceptionFactory.createSysException(TICKET_SEND_FAIL);
            }
        }
    }

    /**
     * 审批成功后发送消息给外部联系人
     *
     * @param ticket   票据对象
     * @param typeEnum 业务类型枚举
     * @throws SysException 业务异常，可能因为ticket没有getId方法而抛出
     */
    @Override
    public void ticketBookSendMessage(Object ticket, TicketBookRelationTypeEnum typeEnum) throws SysException {
        String ticketId = TicketUtils.getId(ticket);
        QueryWrapper<TicketBookRelationEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("obj_id", ticketId);
        queryWrapper.eq("send_status", SEND_STATUS_NO.getCode());
        queryWrapper.eq("type", typeEnum.getCode());
        List<TicketBookRelationEntity> tbrEntityList = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(tbrEntityList)) {
            return;
        }
        Map<Integer, List<TicketBookRelationEntity>> tbrMessageTypeMap
                = tbrEntityList.stream().collect(Collectors.groupingBy(TicketBookRelationEntity::getMessageType));
        List<TicketBookRelationEntity> smsList = tbrMessageTypeMap.get(TBRM_SMS.getCode());
        List<TicketBookRelationEntity> emailList = tbrMessageTypeMap.get(TBRM_EMAIL.getCode());
        List<TicketBookRelationEntity> allList = tbrMessageTypeMap.get(TBRM_SMS_AND_EMAIL.getCode());
        if (null == smsList) {
            smsList = new ArrayList<>();
        }
        if (null == emailList) {
            emailList = new ArrayList<>();
        }
        if (!CollectionUtils.isEmpty(allList)) {
            smsList.addAll(allList);
            emailList.addAll(allList);
        }
        ticketBookSendSms(ticket, smsList, typeEnum);
        ticketBookSendEmail(ticket, emailList, typeEnum);
        log.info("审批成功后发送消息给外部联系人", JSON.toJSONString(tbrEntityList));
    }

    /**
     * 短信通知
     *
     * @param ticket   票据对象
     * @param sendList 联系人对象
     * @param typeEnum 业务类型枚举
     * @throws SysException 业务异常
     */
    private void ticketBookSendSms(Object ticket, List<TicketBookRelationEntity> sendList, TicketBookRelationTypeEnum typeEnum) throws SysException {
        /*
        1、通过TicketUtils工具类获取ticket的数据
        2、根据业务类型选择对应的模板
        3、组合好数据，发送短信给外部联系人
         */
    }

    /**
     * 邮件通知
     *
     * @param ticket   票据对象
     * @param sendList 联系人对象
     * @param typeEnum 业务类型枚举
     * @throws SysException 业务异常
     */
    private void ticketBookSendEmail(Object ticket, List<TicketBookRelationEntity> sendList, TicketBookRelationTypeEnum typeEnum) throws SysException {
        /*
        1、通过TicketUtils工具类获取ticket的数据
        2、根据业务类型选择对应的模板表对应的目标
        3、组合好数据，发送邮件给外部联系人
         */
    }

    /**
     * 通讯录发消息处理
     *
     * @param objId 开立申请id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void ticketBookSendMsgToMq(String objId, List<Integer> type, User user) throws SysException {
        //  2 查询通讯录信息
        QueryWrapper<TicketBookRelationEntity> bookRelationEntityQueryWrapper = new QueryWrapper<>();
        bookRelationEntityQueryWrapper.lambda()
                .eq(TicketBookRelationEntity::getBusinessId, objId)
                .in(TicketBookRelationEntity::getBusinessType, type);
        List<TicketBookRelationEntity> ticketBookRelationEntityList = this.list(bookRelationEntityQueryWrapper);
        if (!CollectionUtils.isEmpty(ticketBookRelationEntityList)) {
            List<String> collect = ticketBookRelationEntityList.stream().map(TicketBookRelationEntity::getAddressBookId).collect(Collectors.toList());
            // 通过企业id 查到企业联系人的 邮箱和 手机号
            List<AddressBookEntity> addressByIds = baseDataFeign.getAddressByIds(collect);
            if (CollectionUtils.isEmpty(addressByIds)) {
                throw new SysException("未找到通讯录人员信息");
            }
            Integer messageType = ticketBookRelationEntityList.get(0).getMessageType();
            SMSEmailParams smsEmailParams = new SMSEmailParams();
            List<String> emailList = addressByIds.stream().map(AddressBookEntity::getUserEmail).collect(Collectors.toList());
            List<String> phoneList = addressByIds.stream().map(AddressBookEntity::getUserPhone).collect(Collectors.toList());
            String phoneStr = StringUtils.join(phoneList, ",");
            if (messageType.equals(1)) {
                // 短信
                smsEmailParams.setTelephoneNumbers(phoneStr);
            } else if (messageType.equals(2)) {
                // 邮件
                smsEmailParams.setReceiveAddress(emailList);
                smsEmailParams.setTitle("开单完成");
            } else {
                smsEmailParams.setTelephoneNumbers(phoneStr);
                smsEmailParams.setReceiveAddress(emailList);
                // 邮件 标题
                smsEmailParams.setTitle("开单完成");
            }
            smsEmailParams.setContent("开单完成");
            sendSms(smsEmailParams);
            //2.2 将联系人数据改为已发送
            List<String> idList = ticketBookRelationEntityList.stream().map(TicketBookRelationEntity::getId).collect(Collectors.toList());
            UpdateWrapper<TicketBookRelationEntity> updaterMapper = new UpdateWrapper<>();
            updaterMapper.lambda().set(TicketBookRelationEntity::getSendStatus
                    , SendStatusEnum.SEND_STATUS_YES.getCode()).in(TicketBookRelationEntity::getId, idList);
            this.update(updaterMapper);

        }
    }

    private void sendSms(SMSEmailParams smsEmailParams) throws SysException {
        Result result = msgFeign.sendBookRelation(smsEmailParams);
        String error = "开单结束，通知外部联系人，消息中心服务错误";
        if (ObjectUtils.isEmpty(result)) {
            throw new SysException(error);
        }
        if (ResultCode.SUCCESS.getCode() != result.getCode()) {
            throw new SysException(error + result.getMsg());
        }
    }

}